﻿using System;

namespace MathService.DSP.Signals
{
	public partial class DigitalSignal
	{
		public static class Standart
		{
			public static DigitalSignal Functional(double dx, double x0, double Length, Func<double, double> Function)
			{
				var lv_N = (int)(Length / dx);
				var lv_Values = new double[lv_N];

				for(var i = 0; i < lv_N; i++) lv_Values[i] = Function(i * dx - x0);

				return new DigitalSignal(dx, lv_Values) { x0 = x0 };
			}

			/* -------------------------------------------------------------------------------------------- */

			public static DigitalSignal Sin(double A, double dx, double Length, double x0, double f,
				double phi0)
			{
				var w = 2 * Math.PI * f;
				return Functional(dx, x0, Length, x => A * Math.Sin(w * x + phi0));
			}

			public static DigitalSignal Sin(double A, double dx, double Length, double x0, double f)
			{
				var w = 2 * Math.PI * f;
				return Functional(dx, x0, Length, x => A * Math.Sin(w * x));
			}

			public static DigitalSignal Cos(double A, double dx, double Length, double x0, double f)
			{
				var w = 2 * Math.PI * f;
				return Functional(dx, x0, Length, x => A * Math.Cos(w * x));
			}

			/* -------------------------------------------------------------------------------------------- */

			public static DigitalSignal Impuls(double dx, double Length, double tau)
			{
				return Impuls(1, dx, Length, tau);
			}

			public static DigitalSignal Impuls(double A, double dx, double Length, double tau, 
				double T = double.MaxValue)
			{
				return Functional(dx, 0, Length, x => (x % T) < tau ? A : 0);
			}

			/* -------------------------------------------------------------------------------------------- */

			public static DigitalSignal Noice(double dx, double Length)
			{
				return Noice(1, dx, Length, 0);
			}

			public static DigitalSignal Noice(double P, double dx, double Length, double Offset)
			{
				var lv_Rnd = new Random(DateTime.Now.Millisecond);
				return Functional(dx, 0, Length,
				                  Arg => P*(lv_Rnd.NextDouble() - 0.5) + Offset);
			}

			/* -------------------------------------------------------------------------------------------- */

			public static DigitalSignal Offset(double dx, double Length)
			{
				return Offset(1, dx, Length);
			}

			public static DigitalSignal Offset(double Offset, double dx, double Length)
			{
				return Functional(dx, 0, Length,
				                  x => Offset);
			}

			/* -------------------------------------------------------------------------------------------- */

			public static DigitalSignal Exp(double dx, double Length, double Alpha)
			{
				return Exp(1, dx, Length, Alpha, 0);
			}

			public static DigitalSignal Exp(double A, double dx, double Length, double Alpha, double x0 = 0)
			{
				return Functional(dx, x0, Length,
				                  x => A*Math.Exp(Alpha*x));
			}

			/* -------------------------------------------------------------------------------------------- */

			public static DigitalSignal DeltaFunction(double dx, double Length)
			{
				return DeltaFunction(1, dx, Length);
			}

			public static DigitalSignal DeltaFunction(double A, double dx, double Length, double x0 = 0)
			{
				return Functional(dx, x0, Length,
				                  x => Math.Abs(x) < dx ? A : 0);
			}

			/* -------------------------------------------------------------------------------------------- */


			/* -------------------------------------------------------------------------------------------- */
		}
	}
}